home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 October: Mac OS SDK / Dev.CD Oct 96 SDK / Dev.CD Oct 96 SDK2.toast / Development Kits (Disc 2) / OpenDoc Development Framework / ODFDev / Clock / Sources / Frame.cpp < prev    next >
Encoding:
Text File  |  1996-08-16  |  18.0 KB  |  616 lines  |  [TEXT/MPS ]

  1. //========================================================================================
  2. //
  3. //    File:                Frame.cpp
  4. //    Release Version:    $ ODF 1 $
  5. //
  6. //    Copyright:    (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  7. //
  8. //========================================================================================
  9.  
  10. #ifndef FRAME_H
  11. #include "Frame.h"
  12. #endif
  13.  
  14. #ifndef PART_H
  15. #include "Part.h"
  16. #endif
  17.  
  18. #ifndef DEFINES_K
  19. #include "Defines.k"
  20. #endif
  21.  
  22. #ifndef CONTENT_H
  23. #include "Content.h"
  24. #endif
  25.  
  26. // ----- Part Layer -----
  27.  
  28. #ifndef FWUTIL_H
  29. #include "FWUtil.h"
  30. #endif
  31.  
  32. #ifndef FWITERS_H
  33. #include "FWIters.h"
  34. #endif
  35.  
  36. #ifndef FWCONTXT_H
  37. #include "FWContxt.h"
  38. #endif
  39.  
  40. #ifndef FWGROWBX_H
  41. #include "FWGrowBx.h"
  42. #endif
  43.  
  44. #ifndef FWSCLBAR_H
  45. #include "FWSclBar.h"
  46. #endif
  47.  
  48. // ----- OS Layer -----
  49.  
  50. #ifndef FWTXTSHP_H
  51. #include "FWTxtShp.h"
  52. #endif
  53.  
  54. #ifndef FWRECSHP_H
  55. #include "FWRecShp.h"
  56. #endif
  57.  
  58. #ifndef FWLINSHP_H
  59. #include "FWLinShp.h"
  60. #endif
  61.  
  62. #ifndef FWOVLSHP_H
  63. #include "FWOvlShp.h"
  64. #endif
  65.  
  66. #ifndef FWODGEOM_H
  67. #include "FWODGeom.h"
  68. #endif
  69.  
  70. #ifndef FWTXTBOX_H
  71. #include "FWTxtBox.h"
  72. #endif
  73.  
  74. #ifndef FWCFMRES_H
  75. #include "FWCFMRes.h"
  76. #endif
  77.  
  78. #ifndef FWRESACC_H
  79. #include "FWResAcc.h"
  80. #endif
  81.  
  82. #ifndef FWRESTYP_H
  83. #include "FWResTyp.h"
  84. #endif
  85.  
  86. #ifndef FWFXMATH_H
  87. #include "FWFxMath.h"
  88. #endif
  89.  
  90. #ifndef FWSCRCON_H
  91. #include "FWScrCon.h"
  92. #endif
  93.  
  94. //========================================================================================
  95. // RunTime information
  96. //========================================================================================
  97.  
  98. #ifdef FW_BUILD_MAC
  99. #pragma segment odfclock
  100. #endif
  101.  
  102. //========================================================================================
  103. // Constants
  104. //========================================================================================
  105.  
  106. const FW_Fixed kClockRadius = FW_IntToFixed(100);    // In logical units
  107. const FW_Fixed kFxPI = FW_DoubleToFixed(3.1415926);
  108.  
  109. //========================================================================================
  110. // class CClockFrame
  111. //========================================================================================
  112.  
  113. FW_DEFINE_AUTO(CClockFrame)
  114.     
  115. //----------------------------------------------------------------------------------------
  116. // CClockFrame::CClockFrame
  117. //----------------------------------------------------------------------------------------
  118.  
  119. CClockFrame::CClockFrame(Environment* ev, ODFrame* odFrame, 
  120.                         FW_CPresentation* presentation, 
  121.                         CClockPart* clockPart,
  122.                         CClockContent* clockContent) :
  123.     FW_CFrame(ev, odFrame, presentation, clockPart),
  124.     fMapping(FW_kCustomConstrained),
  125.     fDigitalFont(FW_kSystemFont, FW_kPlain, FW_IntToFixed(12)),
  126.     fClockContent(clockContent),
  127.     fClockPart(clockPart),
  128.     fLastTime(FW_CTime::GetCurrentTime())
  129. {
  130.     // ----- Load the face string ("OpenDoc") -----
  131.     {
  132.         FW_CSharedLibraryResourceFile resFile(ev);
  133.         ::FW_LoadStringByID(ev, resFile, kClockFaceStrings, MULTISTRINGRES, kClockOpenDocString, fFaceString);
  134.     }
  135. }
  136.  
  137. //----------------------------------------------------------------------------------------
  138. // CClockFrame::~CClockFrame
  139. //----------------------------------------------------------------------------------------
  140.  
  141. CClockFrame::~CClockFrame()
  142. {
  143. }
  144.  
  145. //----------------------------------------------------------------------------------------
  146. // CClockFrame::FacetAdded
  147. //----------------------------------------------------------------------------------------
  148.  
  149. void CClockFrame::FacetAdded(Environment* ev, ODFacet* facet, unsigned short facetCount)
  150. {
  151.     FW_CFrame::FacetAdded(ev, facet, facetCount);
  152.     
  153.     if (facetCount == 1)
  154.     {
  155.         // ----- First reset the mapping. Because ResetMapping needs the window
  156.         // ----- we have to wait for FacetAdded before calling ResetMapping the first time
  157.         this->ResetMapping(ev);
  158.     
  159.         this->UpdateUsedAndActiveShapes(ev);
  160.     }
  161. }
  162.  
  163. //----------------------------------------------------------------------------------------
  164. //    CClockFrame::GetDigitalClockRect
  165. //----------------------------------------------------------------------------------------
  166.  
  167. FW_CRect CClockFrame::GetDigitalClockRect(Environment* ev)
  168. {
  169.     // ----- Calculate a default rectangle size for a digital clock
  170.     FW_CString32 digitalString;
  171.     {
  172.         FW_CSharedLibraryResourceFile resFile(ev);
  173.         ::FW_LoadStringByID(ev, resFile, kClockFaceStrings, MULTISTRINGRES, kClockDigitalWidthString, digitalString);
  174.     }
  175.     
  176.     FW_CTextShape textShape(digitalString,
  177.                             FW_IntToFixed(0),
  178.                             FW_IntToFixed(0),
  179.                             fDigitalFont,
  180.                             FW_kTextAlignLeft | FW_kTextAlignBaseLine);
  181.     
  182.         
  183.     FW_CScreenContext sc(ev);    
  184.     
  185.     FW_CRect rect;
  186.     textShape.GetBounds(sc, rect);
  187.     
  188.     rect.Inset(FW_IntToFixed(-3), FW_IntToFixed(-3));
  189.     
  190.     return rect;
  191. }
  192.         
  193. //----------------------------------------------------------------------------------------
  194. //    CClockFrame::ChangeClockType
  195. //----------------------------------------------------------------------------------------
  196. //    If I switch to analog and my frame is smaller than ff(80) try to request something bigger
  197.  
  198. void CClockFrame::ChangeClockType(Environment* ev, short newClockType)
  199. {
  200.     if (!IsTopFrame(ev) && newClockType == kAnalogClock)
  201.     {
  202.         FW_CRect frameBounds = GetBounds(ev);
  203.         FW_Fixed min = FW_Minimum(frameBounds.Height(), frameBounds.Width());
  204.         
  205.         if (min < FW_IntToFixed(80))
  206.         {
  207.             FW_CAcquiredODShape askedShape = ::FW_NewODShape(ev, FW_CRect(FW_kZeroPoint, FW_IntToFixed(80), FW_IntToFixed(80)));
  208.             this->RequestFrameShape(ev, askedShape);
  209.         }    
  210.     }
  211.     
  212.     UpdateUsedAndActiveShapes(ev);
  213.     ResetMapping(ev);
  214.     Invalidate(ev);
  215. }
  216.  
  217. //----------------------------------------------------------------------------------------
  218. //    CClockFrame::AdjustUsedShape
  219. //----------------------------------------------------------------------------------------
  220. //    'suggestedUsedShape' is equal to the frame shape
  221.  
  222. ODShape* CClockFrame::AdjustUsedShape(Environment* ev, ODShape* suggestedUsedShape)
  223. {    
  224.     if (GetViewType(ev) != FW_CPart::gViewAsFrameToken)
  225.         return FW_CFrame::AdjustUsedShape(ev, suggestedUsedShape);
  226.         
  227.     FW_CRect usedRect = FW_GetShapeBoundingBox(ev, suggestedUsedShape);
  228.  
  229.     ODShape* newUsedShape;
  230.     if (fClockContent->GetClockType() == kAnalogClock)
  231.     {        
  232.         FW_CRect rect(usedRect);
  233.         FW_Fixed height = usedRect.Height();
  234.         FW_Fixed width = usedRect.Width();
  235.         
  236.         if (height < width)
  237.             rect.right = rect.left + height;
  238.         else
  239.             rect.bottom = rect.top + width;
  240.         rect.PlaceInCenter(usedRect);
  241.         
  242.         newUsedShape = ::FW_CreateOvalODShape(ev, rect);
  243.     }
  244.     else
  245.     {    
  246.         
  247.         FW_CRect rect = GetDigitalClockRect(ev);
  248.         rect.PlaceInCenter(usedRect);
  249.         
  250.         newUsedShape = ::FW_NewODShape(ev, rect);
  251.     }
  252.     
  253.     return newUsedShape;
  254. }
  255.  
  256. //----------------------------------------------------------------------------------------
  257. //    CClockFrame::AdjustActiveShape
  258. //----------------------------------------------------------------------------------------
  259. //    [HLX] Because OpenDoc uses the Frame shape as the default active shape I need to 
  260. //    adjust my active shape too.
  261.  
  262. ODShape* CClockFrame::AdjustActiveShape(Environment* ev, ODFacet* facet, ODShape* suggestedActiveShape)
  263. {
  264.     if (GetViewType(ev) != FW_CPart::gViewAsFrameToken)
  265.         return FW_CFrame::AdjustActiveShape(ev, facet, suggestedActiveShape);
  266.  
  267.     suggestedActiveShape->Acquire(ev);
  268.     return suggestedActiveShape;
  269. }
  270.  
  271. //----------------------------------------------------------------------------------------
  272. // CClockFrame::FrameShapeChanged
  273. //----------------------------------------------------------------------------------------
  274.  
  275. void CClockFrame::FrameShapeChanged(Environment* ev)
  276. {
  277.     FW_CFrame::FrameShapeChanged(ev);
  278.     
  279.     this->ResetMapping(ev);
  280.     this->Invalidate(ev);
  281. }
  282.  
  283. //----------------------------------------------------------------------------------------
  284. // CClockFrame::UpdateClock
  285. //----------------------------------------------------------------------------------------
  286.  
  287. void CClockFrame::UpdateClock(Environment* ev, const FW_CTime& time)
  288. {
  289.     FW_CFrameFacetIterator facets(ev, this);
  290.     for (ODFacet* clockFacet = facets.First(ev); facets.IsNotComplete(ev); clockFacet = facets.Next(ev))
  291.     {
  292.         FW_CViewContext fc(ev, this, clockFacet);
  293.         
  294.         if (fClockContent->GetClockType() == kAnalogClock)
  295.         {
  296.              fc.SetMapping(fMapping);
  297.             UpdateAnalogClock(ev, fc, time);
  298.          }
  299.         else
  300.             UpdateDigitalClock(ev, fc, time);
  301.     }
  302.     
  303.     fLastTime = time;
  304. }
  305.  
  306. //----------------------------------------------------------------------------------------
  307. // CClockFrame::Draw
  308. //----------------------------------------------------------------------------------------
  309.  
  310. void CClockFrame::Draw(Environment* ev, ODFacet* odFacet, ODShape* invalidShape)
  311. {
  312.     FW_CViewContext fc(ev, this, odFacet, invalidShape);
  313.  
  314.     // [HLX] This will be moved into an erase adorner
  315.     if (IsRoot(ev))
  316.     {
  317.         FW_CRect invalidRect;
  318.         fc.GetClipRect(invalidRect);
  319.  
  320. #ifdef FW_BUILD_MAC
  321.         FW_CInk ink(FW_kRGBWhite,
  322.                     FW_kRGBWhite,
  323.                     FW_kErase);
  324. #else
  325.         FW_CInk ink(FW_CColor(::GetSysColor(COLOR_WINDOWTEXT), 0),
  326.                     FW_CColor(::GetSysColor(COLOR_APPWORKSPACE), 0),
  327.                     FW_kErase);
  328. #endif
  329.         FW_CRectShape::RenderRect(fc, invalidRect, FW_kFill, ink);
  330.     }
  331.  
  332.     if (fClockContent->GetClockType() == kAnalogClock)
  333.     {
  334.         fc.SetMapping(fMapping);
  335.         
  336.         this->DrawClockFace(ev, fc);
  337.         
  338.         this->DrawSecondHand(ev, fc, FW_IntToFixed(fLastTime.GetSecond()));
  339.         this->DrawMinuteHand(ev, fc, FW_IntToFixed(fLastTime.GetMinute()));
  340.         this->DrawHourHand(ev, fc, FW_IntToFixed(fLastTime.GetHour()), FW_IntToFixed(fLastTime.GetMinute()));
  341.     }
  342.     else
  343.         UpdateDigitalClock(ev, fc, fLastTime);
  344. }
  345.  
  346. //----------------------------------------------------------------------------------------
  347. // CClockFrame::DrawTicks
  348. //----------------------------------------------------------------------------------------
  349.  
  350. static void DrawTicks(FW_CGraphicContext& gc, FW_CLineShape& lineShape, 
  351.                      FW_Fixed xStart, FW_Fixed yStart, 
  352.                      FW_Fixed xEnd, FW_Fixed yEnd)
  353. {
  354.     lineShape.SetLineStart(xStart, yStart);
  355.     lineShape.SetLineEnd(xEnd, yEnd);
  356.     lineShape.Render(gc);
  357.     
  358.     lineShape.SetLineStart(-xStart, yStart);
  359.     lineShape.SetLineEnd(-xEnd, yEnd);
  360.     lineShape.Render(gc);
  361.  
  362.     lineShape.SetLineStart(xStart, -yStart);
  363.     lineShape.SetLineEnd(xEnd, -yEnd);
  364.     lineShape.Render(gc);
  365.     
  366.     lineShape.SetLineStart(-xStart,-yStart);
  367.     lineShape.SetLineEnd(-xEnd, -yEnd);
  368.     lineShape.Render(gc);
  369. }
  370.  
  371. //----------------------------------------------------------------------------------------
  372. // CClockFrame::ResetMapping
  373. //----------------------------------------------------------------------------------------
  374.  
  375. void CClockFrame::ResetMapping(Environment* ev)
  376. {
  377.     FW_CPoint logicalExtent(FW_MultipliedByInt(kClockRadius, 2), FW_MultipliedByInt(kClockRadius, 2));
  378.     FW_CPoint deviceExtent = GetExtent(ev);
  379.  
  380.     fMapping.SetExtents(ev, logicalExtent, deviceExtent);
  381.     fMapping.SetDeviceOrigin(ev, FW_Half(deviceExtent.x), FW_Half(deviceExtent.y));
  382. }
  383.  
  384. //----------------------------------------------------------------------------------------
  385. // CClockFrame::DrawClockFace
  386. //----------------------------------------------------------------------------------------
  387.  
  388. void CClockFrame::DrawClockFace(Environment* ev, FW_CGraphicContext& gc)
  389. {
  390.     // ----- Erase under the clock -----
  391.     FW_CRect ovalRect(-kClockRadius, -kClockRadius, kClockRadius, kClockRadius);
  392.     
  393.     FW_COvalShape::RenderOval(
  394.         gc,
  395.         ovalRect,
  396.         FW_kFill,
  397.         FW_kWhiteEraseInk);
  398.     
  399.     FW_COvalShape::RenderOval(
  400.         gc,
  401.         ovalRect,
  402.         FW_kFrame,
  403.         FW_kNormalInk,
  404.         FW_CStyle(FW_IntToFixed(2)));
  405.  
  406.     // ----- Render the "OpenDoc" string -----
  407.     FW_CTextShape::RenderText(
  408.         gc,
  409.         fFaceString,
  410.         FW_CPoint(FW_IntToFixed(0), - FW_Half(kClockRadius)),
  411.         FW_CFont(FW_kHelvetica, FW_kItalic, FW_DividedByInt(kClockRadius, 5)),
  412.         FW_kTextAlignHCenter | FW_kTextAlignBaseLine);
  413.     
  414.     // Use the symmetry of the clock face to speed up the calculations for drawing the face
  415.     // We only need to calculate points for 45 degrees of the circle.  The remaining points can
  416.     // be inferred from these points
  417.     
  418.     short angle = 0;
  419.     short fiveMinute = 0;
  420.  
  421.     FW_CStyle lineStyle = FW_ODFixedToFixed(0x00008000);    // 1/2
  422.     FW_CLineShape lineShape;
  423.     lineShape.SetStyle(lineStyle);
  424.     
  425.     FW_Fixed xStart, yStart, xEnd, yEnd;
  426.  
  427.     FW_Fixed radius = kClockRadius - FW_IntToFixed(2);    // 2 logical unit
  428.     while (angle < 45)
  429.     {
  430.         // ----- convert angle to radians -----
  431.         FW_Fixed radians = FW_DividedByInt(kFxPI * FW_IntToFixed(90 - angle), 180);
  432.         FW_Fixed cosRadian = FW_Cos(radians);
  433.         FW_Fixed sinRadian = FW_Sin(radians);
  434.  
  435.         xStart = radius * cosRadian;
  436.         yStart = radius * sinRadian;
  437.         
  438.         FW_Fixed tickRadius;
  439.         if (fiveMinute == 0)
  440.         {
  441.             tickRadius = radius - FW_DividedByInt(radius, 10);
  442.             fiveMinute = 4;
  443.         }
  444.         else
  445.         {
  446.             tickRadius = radius - FW_DividedByInt(radius, 20);
  447.             fiveMinute--;
  448.         }
  449.  
  450.         xEnd = tickRadius * cosRadian;
  451.         yEnd = tickRadius * sinRadian;
  452.  
  453.         DrawTicks(gc, lineShape, xStart, yStart, xEnd, yEnd);
  454.         
  455.         DrawTicks(gc, lineShape, yStart, xStart, yEnd, xEnd);
  456.  
  457.         angle += 6;
  458.     }
  459. }
  460.  
  461. //----------------------------------------------------------------------------------------
  462. //    CalcPoint
  463. //----------------------------------------------------------------------------------------
  464.  
  465. static FW_CPoint CalcPoint(FW_Fixed radius, FW_Fixed angle)
  466. {
  467.     return FW_CPoint(
  468.         radius * FW_Sin(angle),
  469.         - radius * FW_Cos(angle));
  470. }
  471.  
  472. //----------------------------------------------------------------------------------------
  473. // ::DegreesToRadians
  474. //----------------------------------------------------------------------------------------
  475.  
  476. static inline FW_Fixed DegreesToRadians(FW_Fixed degrees)
  477. {
  478.     return FW_DividedByInt(degrees * kFxPI, 180);
  479. }
  480.  
  481. //----------------------------------------------------------------------------------------
  482. // CClockFrame::DrawHourHand
  483. //----------------------------------------------------------------------------------------
  484.  
  485. void CClockFrame::DrawHourHand(Environment* ev, 
  486.                                 FW_CGraphicContext& gc, 
  487.                                 FW_Fixed hour, 
  488.                                 FW_Fixed minute)
  489. {
  490.     FW_Fixed hourRadius = FW_DividedByInt(kClockRadius, 2);    // Make the hour hand short and stubby
  491.  
  492.     if (hour > FW_IntToFixed(11))
  493.         hour -= FW_IntToFixed(12);
  494.     
  495.     // ----- Divide the clock face into degrees.  
  496.     // ----- Hour hand falls on every five minutes or every 30 degrees
  497.     FW_Fixed radians = ::DegreesToRadians(FW_MultipliedByInt(hour, 30) + FW_Half(minute));
  498.     
  499.     FW_CPoint newPoint = ::CalcPoint(hourRadius, radians);
  500.  
  501.     FW_CStyle style(FW_IntToFixed(3));
  502.     FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
  503.     lineShape.SetInk(FW_kInvertInk);
  504.     lineShape.SetStyle(style);
  505.     lineShape.Render(gc);
  506. }
  507.  
  508. //----------------------------------------------------------------------------------------
  509. // CClockFrame::DrawMinuteHand
  510. //----------------------------------------------------------------------------------------
  511.  
  512. void CClockFrame::DrawMinuteHand(Environment* ev, 
  513.                                 FW_CGraphicContext& gc, 
  514.                                 FW_Fixed minute)
  515. {
  516.     FW_Fixed minuteRadius = kClockRadius * FW_DoubleToFixed(0.8);  // Make the minute hand longer than the hour hand
  517.     
  518.     // ----- Divide the clock face into degrees.  
  519.     // ----- (360 degrees divided by 60 minutes is 6 degrees per minute)
  520.     FW_Fixed radians = ::DegreesToRadians(FW_MultipliedByInt(minute, 6));
  521.  
  522.     FW_CPoint newPoint = ::CalcPoint(minuteRadius, radians);
  523.  
  524.     FW_CStyle style(FW_IntToFixed(2));
  525.     FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
  526.     lineShape.SetInk(FW_kInvertInk);
  527.     lineShape.SetStyle(style);
  528.     lineShape.Render(gc);
  529. }
  530.  
  531. //----------------------------------------------------------------------------------------
  532. // CClockFrame::DrawSecondHand
  533. //----------------------------------------------------------------------------------------
  534.  
  535. void CClockFrame::DrawSecondHand(Environment* ev, 
  536.                                 FW_CGraphicContext& gc, 
  537.                                 FW_Fixed second)
  538. {
  539.     FW_Fixed secondRadius = kClockRadius * FW_DoubleToFixed(0.9);    // A nice sweeping second hand
  540.  
  541.     // ----- Divide the clock face into degrees.  
  542.     // ----- (360 degrees divided by 60 seconds is 6 degrees per second)
  543.     FW_Fixed radians = ::DegreesToRadians(FW_MultipliedByInt(second, 6));
  544.     
  545.     FW_CPoint newPoint = ::CalcPoint(secondRadius, radians);
  546.  
  547.     FW_CLineShape lineShape(FW_kZeroPoint, newPoint);
  548.     lineShape.SetInk(FW_kInvertInk);
  549.     lineShape.Render(gc);
  550. }
  551.  
  552. //----------------------------------------------------------------------------------------
  553. // CClockFrame::UpdateAnalogClock
  554. //----------------------------------------------------------------------------------------
  555.  
  556. void CClockFrame::UpdateAnalogClock(Environment* ev, 
  557.                                     FW_CGraphicContext& gc, 
  558.                                     const FW_CTime& time)
  559. {    
  560.     // ----- Since we're called every second go ahead and update the second hand
  561.     this->DrawSecondHand(ev, gc, FW_IntToFixed(fLastTime.GetSecond()));
  562.     this->DrawSecondHand(ev, gc, FW_IntToFixed(time.GetSecond()));
  563.  
  564.     if (fLastTime.GetMinute() != time.GetMinute())
  565.     {
  566.         this->DrawMinuteHand(ev, gc, FW_IntToFixed(fLastTime.GetMinute()));
  567.         this->DrawMinuteHand(ev, gc, FW_IntToFixed(time.GetMinute()));
  568.         
  569.         this->DrawHourHand(ev, gc, FW_IntToFixed(fLastTime.GetHour()), FW_IntToFixed(fLastTime.GetMinute()));
  570.         this->DrawHourHand(ev, gc, FW_IntToFixed(time.GetHour()), FW_IntToFixed(time.GetMinute()));
  571.     }
  572. }
  573.  
  574. //----------------------------------------------------------------------------------------
  575. // CClockFrame::UpdateDigitalClock
  576. //----------------------------------------------------------------------------------------
  577.  
  578. void CClockFrame::UpdateDigitalClock(Environment* ev, 
  579.                                     FW_CGraphicContext& gc, 
  580.                                     const FW_CTime& time)
  581. {
  582.     FW_CString255 timeString;
  583.     time.GetTimeString(timeString, TRUE);
  584.  
  585.     FW_CAcquiredODShape aqUsedShape(this->AcquireUsedShape(ev, NULL));
  586.     FW_CRect usedShapeRect = FW_GetShapeBoundingBox(ev, aqUsedShape);
  587.     
  588.     FW_CRectShape rectShape(usedShapeRect, FW_kFill);
  589.     rectShape.SetInk(FW_kWhiteEraseInk);
  590.     rectShape.Render(gc);
  591.     
  592.     rectShape.SetRenderVerb(FW_kFrame);
  593.     rectShape.Render(gc);
  594.     
  595.     FW_CTextBoxShape::RenderTextBox(gc, timeString, usedShapeRect, fDigitalFont, FW_kTextBoxJustifyHCenter);
  596. }
  597.  
  598. //----------------------------------------------------------------------------------------
  599. //     CClockFrame::CreateSubViews
  600. //----------------------------------------------------------------------------------------
  601.  
  602. void CClockFrame::CreateSubViews(Environment* ev)
  603. {        
  604.     // ----- Create a GrowBox only in root frame
  605.     if (this->IsRoot(ev)) 
  606.     {
  607.         FW_CRect frameRect = GetBounds(ev);  
  608.         FW_CPoint sbSize = FW_CScrollBar::GetDefaultScrollBarSize();
  609.         frameRect.right -= sbSize.x;
  610.         frameRect.bottom -= sbSize.y;
  611.         
  612.         FW_CGrowBox* growBox = new FW_CGrowBox(ev, this, 0, frameRect.BotRight());
  613.     }
  614.  
  615. }
  616.